import {
  Controller,
  Get,
  Post,
  Put,
  Delete,
  Patch,
  Body,
  Param,
  Query,
  UseGuards,
  HttpCode,
  HttpStatus
} from '@nestjs/common'
import { ApiTags, ApiOperation } from '@nestjs/swagger'
import { CategoryService } from './category.service'
import {
  CreateCategoryDto,
  UpdateCategoryDto,
  QueryCategoryDto,
  CategoryResponseDto,
  CategoryStatsDto,
  BulkCategoryOperationDto,
  CategoryTreeDto
} from '../../common/dto/category.dto'
import { BatchCategoryDto } from './dto'
import { PaginationResponseDto } from '../../common/dto/base.dto'
import { JwtAuthGuard, RolesGuard, PermissionsGuard } from '../../common/guards/auth.guard'
import { Auth, Public, ContentAuth, SystemAuth } from '../../common/decorators/auth.decorator'
import { CurrentUser } from '../../common/decorators/user.decorator'
import type { UserInfo } from '../../common/decorators/user.decorator'
import {
  ApiDoc,
  ApiPagination,
  ApiCreate,
  ApiUpdate,
  ApiDelete,
  ApiFindOne,
  ApiBatch,
  ApiStats
} from '../../common/decorators/api.decorator'
import { ResponseMessage, Cache, SkipCache } from '../../common/decorators/response.decorator'
import { LoggerService } from '../../common/logger/logger.service'

@ApiTags('分类管理')
@Controller('categories')
export class CategoryController {
  constructor(
    private readonly categoryService: CategoryService,
    private readonly logger: LoggerService
  ) {}

  @Post()
  @ContentAuth.CategoryCreate()
  @ApiCreate(CategoryResponseDto, '创建分类', '创建新的内容分类')
  @ResponseMessage('分类创建成功')
  async create(
    @Body() createCategoryDto: CreateCategoryDto,
    @CurrentUser() currentUser: UserInfo
  ): Promise<CategoryResponseDto> {
    this.logger.info('创建分类请求', {
      operator: currentUser.id,
      name: createCategoryDto.name,
      parentId: createCategoryDto.parentId
    })

    const category = await this.categoryService.create(createCategoryDto, currentUser.id)

    this.logger.info('分类创建成功', {
      operator: currentUser.id,
      categoryId: category.id,
      name: category.name,
      slug: category.slug
    })

    return category
  }

  @Get()
  @Public()
  @ApiPagination(CategoryResponseDto, '获取分类列表', '分页获取分类列表，支持多种筛选条件')
  @Cache(600) // 缓存10分钟
  async findAll(@Query() queryDto: QueryCategoryDto): Promise<PaginationResponseDto<CategoryResponseDto>> {
    this.logger.debug('获取分类列表请求', {
      query: queryDto
    })

    const categories = await this.categoryService.findAll(queryDto)

    // 构造分页响应
    return {
      data: categories,
      total: categories.length,
      page: queryDto.page || 1,
      limit: queryDto.limit || 10,
      totalPages: Math.ceil(categories.length / (queryDto.limit || 10)),
      hasNext: false,
      hasPrev: false
    }
  }

  @Get('tree')
  @Public()
  @ApiDoc({
    summary: '获取分类树',
    description: '获取完整的分类树结构'
  })
  @Cache(600) // 缓存10分钟
  async getTree(
    @Query('maxDepth') maxDepth?: number,
    @Query('includeEmpty') includeEmpty: boolean = false
  ): Promise<CategoryTreeDto[]> {
    this.logger.debug('获取分类树请求', {
      maxDepth,
      includeEmpty
    })

    return this.categoryService.getTree(maxDepth, includeEmpty)
  }

  @Get('root')
  @Public()
  @ApiDoc({
    summary: '获取根分类',
    description: '获取所有根级分类（没有父分类的分类）'
  })
  @Cache(600) // 缓存10分钟
  async getRootCategories(@Query('includeChildren') includeChildren: boolean = false): Promise<CategoryResponseDto[]> {
    this.logger.debug('获取根分类请求', {
      includeChildren
    })

    return this.categoryService.getRootCategories(includeChildren)
  }

  @Get('popular')
  @Public()
  @ApiDoc({
    summary: '获取热门分类',
    description: '根据内容数量获取热门分类'
  })
  @Cache(1800) // 缓存30分钟
  async getPopularCategories(
    @Query('limit') limit: number = 10
  ): Promise<Array<CategoryResponseDto & { contentCount: number }>> {
    this.logger.debug('获取热门分类请求', {
      limit
    })

    return this.categoryService.getPopularCategories(limit)
  }

  @Get('stats')
  @ContentAuth.CategoryManage()
  @ApiStats('获取分类统计', '获取分类相关的统计数据')
  @Cache(600) // 缓存10分钟
  async getStats(@CurrentUser() currentUser: UserInfo): Promise<CategoryStatsDto> {
    this.logger.debug('获取分类统计请求', {
      operator: currentUser.id
    })

    return this.categoryService.getStats()
  }

  @Get('search')
  @Public()
  @ApiDoc({
    summary: '搜索分类',
    description: '根据名称或描述搜索分类'
  })
  @Cache(300) // 缓存5分钟
  async search(@Query('q') query: string, @Query('limit') limit: number = 20): Promise<CategoryResponseDto[]> {
    this.logger.debug('搜索分类请求', {
      query,
      limit
    })

    return this.categoryService.search(query, limit)
  }

  @Get(':id')
  @Public()
  @ApiFindOne(CategoryResponseDto, '获取分类详情', '根据ID获取分类详细信息')
  @Cache(600) // 缓存10分钟
  async findOne(
    @Param('id') id: string,
    @Query('includeChildren') includeChildren?: boolean,
    @Query('includeParent') includeParent?: boolean,
    @Query('includeContent') includeContent?: boolean
  ): Promise<CategoryResponseDto> {
    this.logger.debug('获取分类详情请求', {
      categoryId: id,
      includeChildren,
      includeParent,
      includeContent
    })

    return this.categoryService.findById(id, {
      includeChildren: includeChildren ?? false,
      includeParent: includeParent ?? false,
      includeContent: includeContent ?? false
    })
  }

  @Put(':id')
  @ContentAuth.CategoryEdit()
  @ApiUpdate(CategoryResponseDto, '更新分类', '更新指定分类的信息')
  @ResponseMessage('分类更新成功')
  @SkipCache() // 跳过缓存
  async update(
    @Param('id') id: string,
    @Body() updateCategoryDto: UpdateCategoryDto,
    @CurrentUser() currentUser: UserInfo
  ): Promise<CategoryResponseDto> {
    this.logger.info('更新分类请求', {
      operator: currentUser.id,
      categoryId: id,
      data: updateCategoryDto
    })

    const category = await this.categoryService.update(id, updateCategoryDto)

    this.logger.info('分类更新成功', {
      operator: currentUser.id,
      categoryId: id,
      name: category.name,
      updatedFields: Object.keys(updateCategoryDto)
    })

    return category
  }

  @Delete(':id')
  @ContentAuth.CategoryDelete()
  @ApiDelete('删除分类', '删除指定的分类')
  @HttpCode(HttpStatus.NO_CONTENT)
  @ResponseMessage('分类删除成功')
  @SkipCache() // 跳过缓存
  async remove(
    @Param('id') id: string,
    @CurrentUser() currentUser: UserInfo,
    @Query('moveContentTo') moveContentTo?: string
  ): Promise<void> {
    this.logger.info('删除分类请求', {
      operator: currentUser.id,
      categoryId: id,
      moveContentTo
    })

    await this.categoryService.remove(id, moveContentTo, currentUser.id)

    this.logger.info('分类删除成功', {
      operator: currentUser.id,
      categoryId: id,
      moveContentTo
    })
  }

  @Patch(':id/move')
  @ContentAuth.CategoryEdit()
  @ApiDoc({
    summary: '移动分类',
    description: '将分类移动到新的父分类下'
  })
  @ResponseMessage('分类移动成功')
  @SkipCache() // 跳过缓存
  async move(
    @Param('id') id: string,
    @Body() body: { parentId?: string; position?: number },
    @CurrentUser() currentUser: UserInfo
  ): Promise<CategoryResponseDto> {
    this.logger.info('移动分类请求', {
      operator: currentUser.id,
      categoryId: id,
      newParentId: body.parentId,
      position: body.position
    })

    const category = await this.categoryService.move(id, currentUser.id, body.parentId, body.position)

    this.logger.info('分类移动成功', {
      operator: currentUser.id,
      categoryId: id,
      newParentId: body.parentId,
      name: category.name
    })

    return category
  }

  @Patch(':id/reorder')
  @ContentAuth.CategoryEdit()
  @ApiDoc({
    summary: '重新排序分类',
    description: '调整分类的显示顺序'
  })
  @ResponseMessage('分类排序更新成功')
  @SkipCache() // 跳过缓存
  async reorder(
    @Param('id') id: string,
    @Body() body: { sortOrder: number },
    @CurrentUser() currentUser: UserInfo
  ): Promise<CategoryResponseDto> {
    this.logger.info('重新排序分类请求', {
      operator: currentUser.id,
      categoryId: id,
      newSortOrder: body.sortOrder
    })

    const category = await this.categoryService.updateSortOrder(id, body.sortOrder, currentUser.id)

    this.logger.info('分类排序更新成功', {
      operator: currentUser.id,
      categoryId: id,
      newSortOrder: body.sortOrder,
      name: category.name
    })

    return category
  }

  @Get(':id/children')
  @Public()
  @ApiDoc({
    summary: '获取子分类',
    description: '获取指定分类的所有子分类'
  })
  @Cache(600) // 缓存10分钟
  async getChildren(
    @Param('id') id: string,
    @Query('recursive') recursive?: boolean,
    @Query('includeContent') includeContent?: boolean
  ): Promise<CategoryResponseDto[]> {
    this.logger.debug('获取子分类请求', {
      parentId: id,
      recursive,
      includeContent
    })

    return this.categoryService.getChildren(id, recursive ?? false, includeContent ?? false)
  }

  @Get(':id/ancestors')
  @Public()
  @ApiDoc({
    summary: '获取祖先分类',
    description: '获取指定分类的所有祖先分类（面包屑导航）'
  })
  @Cache(600) // 缓存10分钟
  async getAncestors(@Param('id') id: string): Promise<CategoryResponseDto[]> {
    this.logger.debug('获取祖先分类请求', {
      categoryId: id
    })

    return this.categoryService.getAncestors(id)
  }

  @Get(':id/siblings')
  @Public()
  @ApiDoc({
    summary: '获取兄弟分类',
    description: '获取与指定分类同级的其他分类'
  })
  @Cache(600) // 缓存10分钟
  async getSiblings(
    @Param('id') id: string,
    @Query('includeSelf') includeSelf?: boolean
  ): Promise<CategoryResponseDto[]> {
    this.logger.debug('获取兄弟分类请求', {
      categoryId: id,
      includeSelf
    })

    return this.categoryService.getSiblings(id, includeSelf ?? false)
  }

  @Get(':id/content')
  @Public()
  @ApiDoc({
    summary: '获取分类内容',
    description: '获取指定分类下的所有内容'
  })
  @Cache(300) // 缓存5分钟
  async getCategoryContent(
    @Param('id') id: string,
    @Query('page') page?: number,
    @Query('limit') limit?: number,
    @Query('includeChildren') includeChildren?: boolean,
    @Query('status') status?: string,
    @Query('type') type?: string
  ): Promise<any> {
    this.logger.debug('获取分类内容请求', {
      categoryId: id,
      page,
      limit,
      includeChildren,
      status,
      type
    })

    return this.categoryService.getCategoryContent(id, {
      page: page ?? 1,
      limit: limit ?? 20,
      includeChildren: includeChildren ?? false,
      status,
      type
    })
  }

  @Post('batch')
  @ContentAuth.CategoryManage()
  @ApiBatch('批量操作分类', '批量创建、更新或删除分类')
  @ResponseMessage('批量操作完成')
  @SkipCache() // 跳过缓存
  async batchOperation(
    @Body() batchDto: BatchCategoryDto,
    @CurrentUser() currentUser: UserInfo
  ): Promise<{
    success: number
    failed: number
    errors: Array<{ index: number; error: string }>
  }> {
    this.logger.info('批量操作分类请求', {
      operator: currentUser.id,
      operation: batchDto.operation,
      count: batchDto.items.length
    })

    const result = await this.categoryService.batchOperation(batchDto, currentUser.id)

    this.logger.info('批量操作分类完成', {
      operator: currentUser.id,
      operation: batchDto.operation,
      success: result.success,
      failed: result.failed
    })

    return result
  }

  @Post('rebuild-tree')
  @SystemAuth.SystemManage()
  @ApiDoc({
    summary: '重建分类树',
    description: '重新构建分类的层级关系和路径'
  })
  @ResponseMessage('分类树重建成功')
  @SkipCache() // 跳过缓存
  async rebuildTree(@CurrentUser() currentUser: UserInfo): Promise<{ message: string; processedCount: number }> {
    this.logger.info('重建分类树请求', {
      operator: currentUser.id
    })

    const result = await this.categoryService.rebuildTree(currentUser.id)

    this.logger.info('分类树重建成功', {
      operator: currentUser.id,
      processedCount: result.processedCount
    })

    return result
  }

  @Post('validate-tree')
  @ContentAuth.CategoryManage()
  @ApiDoc({
    summary: '验证分类树',
    description: '检查分类树的完整性和一致性'
  })
  async validateTree(@CurrentUser() currentUser: UserInfo): Promise<{
    isValid: boolean
    issues: Array<{
      type: string
      categoryId: string
      message: string
    }>
  }> {
    this.logger.info('验证分类树请求', {
      operator: currentUser.id
    })

    const result = await this.categoryService.validateTree()

    this.logger.info('分类树验证完成', {
      operator: currentUser.id,
      isValid: result.isValid,
      issuesCount: result.issues.length
    })

    return result
  }

  @Get('slug/:slug')
  @Public()
  @ApiDoc({
    summary: '根据别名获取分类',
    description: '根据分类别名获取分类信息'
  })
  @Cache(600) // 缓存10分钟
  async findBySlug(
    @Param('slug') slug: string,
    @Query('includeChildren') includeChildren?: boolean,
    @Query('includeContent') includeContent?: boolean
  ): Promise<CategoryResponseDto> {
    this.logger.debug('根据别名获取分类请求', {
      slug,
      includeChildren,
      includeContent
    })

    return this.categoryService.findBySlug(slug, {
      includeChildren: includeChildren ?? false,
      includeContent: includeContent ?? false
    })
  }
}
